import { compose } from '@platformatic/graphql-composer'

const placeholderSdl = 'Query { _info: String }'
const placeholderResolvers = { Query: { _info: '@platformatic/gateway' } }

// TODO support subscriptions
// const defaultSubscriptionsOptions = {
//   onError: function onGatewaySubscriptionsError (ctx, topic, err) {
//     // TODO log.error({err})
//     throw err
//   },
//   publish (ctx, topic, payload) {
//     ctx.pubsub.publish({ topic, payload })
//   },
//   subscribe (ctx, topic) {
//     return ctx.pubsub.subscribe(topic)
//   },
//   unsubscribe (ctx, topic) {
//     ctx.pubsub.close()
//   }
// }

function toGatewayOptions (options, app) {
  return {
    logger: app.log,
    defaultArgsAdapter: options?.defaultArgsAdapter,
    addEntitiesResolvers: options?.addEntitiesResolvers,
    entities: options?.entities,
    onSubgraphError: (err, subgraphName) => {
      app.log.error({ err }, 'graphql composer error on subgraph ' + subgraphName)

      if (options?.onSubgraphError) {
        try {
          options.onSubgraphError(err, subgraphName)
        } catch (err) {
          app.log.error({ err }, 'running onSubgraphError')
        }
      }
    }
  }
}

export function createSupergraph ({ sdl = null, resolvers = {} } = {}) {
  // in case of temporary failures of subgraphs on watching, the application can restart if no subgraphs are (tempoary) available
  if (!sdl) {
    return {
      sdl: placeholderSdl,
      resolvers: placeholderResolvers
    }
  }
  return { sdl, resolvers }
}

export function isSameGraphqlSchema (a, b) {
  // TODO review
  return a?.sdl === b?.sdl
}

export function applicationToSubgraphConfig (application) {
  if (!application.graphql) {
    return
  }
  return {
    name: application.graphql.name || application.id || application.origin,
    entities: application.graphql.entities,
    server: {
      host: application.graphql.host || application.origin,
      composeEndpoint: application.graphql.composeEndpoint,
      graphqlEndpoint: application.graphql.graphqlEndpoint
    }
  }
}

export async function fetchGraphqlSubgraphs (applications, options, app) {
  const subgraphs = applications.map(applicationToSubgraphConfig).filter(s => !!s)
  const gateway = await compose({ ...toGatewayOptions(options, app), subgraphs })

  return createSupergraph({
    logger: app.log,
    sdl: gateway.toSdl(),
    resolvers: gateway.resolvers
  })
}
